release: v1.4.0#9160
Open
sriramveeraghanta wants to merge 22 commits into
Open
Conversation
Bumps the npm_and_yarn group with 1 update in the /packages/tailwind-config directory: [postcss](https://github.com/postcss/postcss). Updates `postcss` from 8.5.6 to 8.5.10 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](postcss/postcss@8.5.6...8.5.10) --- updated-dependencies: - dependency-name: postcss dependency-version: 8.5.10 dependency-type: direct:production dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* fix: filter out soft-deleted states from API endpoints - Add deleted_at__isnull=True filter to StateListCreateAPIEndpoint.get_queryset() - Add deleted_at__isnull=True filter to StateDetailAPIEndpoint.get_queryset() - Prevents soft-deleted states from reappearing in UI after navigation - Fixes #8829 * Fix: exclude issues linked to soft-deleted states
Drop four overrides that no package in the workspace depends on (direct or transitive): js-yaml, happy-dom, tar-fs, and @isaacs/brace-expansion. Verified against pnpm-lock.yaml — no resolved entries existed, so the overrides were dead weight.
`ProjectViewSet.partial_update`, `BulkEstimatePointEndpoint.partial_update`, and `WorkspaceUserProfileEndpoint.get` previously fetched objects by primary key alone after a workspace-scoped permission check, allowing an authenticated caller to act on resources belonging to other workspaces by supplying a foreign UUID with their own workspace slug in the URL. - Project partial_update: scope `Project.objects.get` by `workspace__slug`, matching the existing pattern in `destroy`. - Bulk estimate partial_update: scope `Estimate.objects.get` by `workspace__slug` and `project_id`, matching `retrieve` and `destroy`. - Workspace user profile: require the target `user_id` to be an active member of the requested workspace before returning email and other PII.
…or (#8935) X-Forward-For is not a real HTTP header — the standard is X-Forwarded-For. With the typo, Nginx never replaces $remote_addr with the actual client IP, so rate limiting and IP logging see the proxy IP instead of the real client. Affects all three nginx configs (web, admin, space).
…tes (GHSA-x63v-p7wc-47x4) (#9014) is_workspace_admin in ProjectMemberViewSet.partial_update was derived from the target member's workspace role, not the requester's. When the target happened to be a workspace admin, all three project-role guards (L231/238/247) were bypassed regardless of who was making the request, allowing a non-admin requester to re-role a workspace admin's project membership. Compute is_workspace_admin from the requester instead and keep the target's workspace role under a distinct name for the existing new-role-vs-workspace-role cap.
* chore: update completed_at logic updation in Issue save method * fix: update error handling Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * fix: use StateGroup Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* refactor(i18n): migrate packages/i18n from MobX to react-i18next with per-feature namespaces
Replaces the internals of packages/i18n with react-i18next while preserving the
identical public API. Consumer code using useTranslation() and TranslationProvider
requires no changes.
Translation file format: TS objects to JSON namespaces
- Converted TypeScript translation files (19 languages) into feature-based JSON namespace files
- Split the monolithic translations.ts into per-feature namespace files: workspace.json,
project.json, work-item.json, cycle.json, inbox.json, etc.
- 30 community namespaces across 19 languages = 570 JSON files
Core runtime: MobX to i18next
- Replaced MobX TranslationStore with an i18next instance using i18next-icu
(preserves ICU MessageFormat) and i18next-resources-to-backend (namespace lazy loading)
- useTranslation() and TranslationProvider keep identical signatures
- All namespaces pre-loaded during init for the current language to prevent
re-render cascades
- Reads saved language from localStorage before init for faster first paint
Build tooling
- scripts/generate-types.ts: Reads English JSON files and outputs keys.generated.ts
with a flat union of translation keys (runs before every build)
- scripts/sync-check.ts: Cross-locale missing/stale key detection, cross-namespace
collision detection, path conflict detection (supports --ci mode)
App-level changes
- Removed useTranslation-based language sync effect from store-wrapper
- Language is now synced imperatively from profile.store (fetchUserProfile,
updateUserProfile) and root.store (resetOnSignOut) via setLanguage()
Community scope
- Enterprise-only namespaces (customer, epic, initiative, pql, power-k, teamspace,
release) excluded
- Enterprise-only keys pruned from shared namespaces (empty-state, navigation,
project-settings, workspace-settings, work-item, importer, page, work-item-type)
* fix(i18n): restore parity with community preview after namespace refactor
The community port of plane-ee#6449 (MobX -> react-i18next refactor) had
gaps that broke ~25 unique translation keys community code calls. This
commit restores parity:
- Port power-k namespace (19 locales) from plane-ee, stripped of EE-only
paths (initiative/customer/teamspace/dashboards/AI assistant). Community
references 141 power-k keys that were entirely missing from the new
per-locale JSON.
- Restore epic.* keys (8 leaves) into work-item.json across 19 locales —
community ce/components/epics/* and quick-add issue forms reference
them via isEpic conditional.
- Add 'date' leaf to common.json across 19 locales (sourced from
work_item_types.settings.properties.property_type.date.label so the
proper translation, not English, is used).
- Move exporter.* subtree from importer.json to common.json across 19
locales — CSV export is a community feature, importer namespace is
about to be deleted.
- Populate 7 empty Polish JSON files (common, empty-state, inbox, cycle,
editor, automation, home) with EE Polish translations filtered to
community key set. The community port committed these as 0-byte files.
- Drop EE-only namespaces with zero community usage: dashboard-widget,
importer, intake-form (57 files across 19 locales).
- Update NAMESPACES const: drop the 3 deleted namespaces, add power-k.
- Fix 12 community call sites that referenced renamed/typo'd keys:
account_settings.api_tokens.heading -> .title
auth.common.password.toast.error.* -> .change_password.error.*
sign_out.toast.error.* -> auth.sign_out.toast.error.*
notification.toasts.un_snoozed -> .unsnoozed
profile.stats.priority_distribution.priority -> common.priority
projects.label -> common.projects
progress -> common.progress
epics -> common.epics
creating_theme -> common.saving (no localized source available)
toast.error (with trailing space typo) -> toast.error
Verified: every literal t(...) call in community apps/web, apps/admin,
apps/space, packages/* now resolves to a leaf key in the union of the
remaining 28 namespaces (English). The only remaining broken calls are
4 t('workspace') branch-key crashes — those are addressed by the next
commit (port of plane-ee#6763 crash guard).
Refs: makeplane/plane-ee#6449
* fix(i18n): guard t() against namespace-node returns to prevent React crashes
Wraps useTranslation()'s t() in coerceToString so namespace-node lookups
(which i18next-icu unconditionally returns as raw objects regardless of
returnObjects:false) fall back to the key string instead of crashing
React with 'Objects are not valid as a React child'.
Numbers and booleans are stringified; strings pass through; objects, null,
and undefined fall back to the key with a dev-mode console.warn pointing
to the bad call site. Production builds suppress the warning but keep the
guard. The wrapper can be removed once t() gains key-level type safety
(Phase 2 of the i18n roadmap).
Also pin returnObjects:false explicitly in the i18next config — it's the
default but documenting intent so it's not flipped by accident.
Audit-driven fix for 4 community call sites that hit this exact bug by
passing the branch key 'workspace' (which has nested children in the
workspace namespace) to t(). Switched to t('common.workspace') (existing
leaf with value 'Workspace').
Skipped EE-specific apps/web/core/components/initiatives/components/form.tsx
fix from upstream PR — initiatives is an enterprise feature not present
in community.
Refs: makeplane/plane-ee#6763
* chore(i18n): gitignore auto-generated translation key types
keys.generated.ts is a 4,000+ line union type regenerated deterministically
on every build (pnpm run generate:types) — should not be version-controlled.
Adding the file to .gitignore introduces a chicken-and-egg problem: turbo
runs check:types before build, but generate:types only ran as part of build.
On a fresh clone with no keys.generated.ts present, tsc --noEmit fails. Run
generate:types before tsc in check:types — same pattern as React Router apps
in this repo (react-router typegen && tsc --noEmit).
- Add packages/i18n/src/types/keys.generated.ts to root .gitignore
- Untrack the file from git (git rm --cached)
- Run generate:types before tsc in check:types
Verified: deleting keys.generated.ts and running check:types regenerates
the file correctly. After regeneration, git status shows the file remains
untracked (.gitignore is honored).
Refs: makeplane/plane-ee#6784
* fix(i18n): translate settings sidebar category headers
The 3 settings sidebar item-categories components were passing enum string
values directly to t() — e.g. t('your profile'), t('work-structure'),
t('administration'). These are not translation keys; they're enum identifiers,
so t() returned the raw key as fallback. Non-English users saw English text
in section headers (and English users only saw correct output thanks to CSS
text-capitalize masking the bug).
Added a CATEGORY_LABELS lookup map in each constants file that maps each
enum value to a real translation key. Components now call t(LABELS[category])
instead of t(category).
- Added 5 new keys to en/common.json common.* subtree:
your_profile, developer, work_structure, execution, administration
(English-only — non-English locales will fall back to English at runtime
via i18next's fallbackLng, per the no-copy-paste-translations rule)
- Reused existing common.general and common.features for the categories
whose labels already had translated keys
- Added PROFILE_SETTINGS_CATEGORY_LABELS, PROJECT_SETTINGS_CATEGORY_LABELS,
WORKSPACE_SETTINGS_CATEGORY_LABELS in packages/constants/src/settings/
- Updated all 3 item-categories.tsx components
Found via comprehensive dynamic-key audit (1918 t() invocations classified
across literal, template-literal, property-access, conditional, function-call,
and identifier patterns). Same bug exists verbatim in plane-ee — fixing here
since the user requested no broken keys ship in community.
* chore: untrack Claude Code runtime lockfile
.claude/scheduled_tasks.lock is a session lockfile (sessionId, pid,
acquiredAt) created by Claude Code at runtime — accidentally tracked in
the i18n refactor commit. Untrack from git; the file stays on disk for
the running session.
* fix(i18n): type-safe coerceToString call + bump lint ceiling
Two post-Commit D follow-ups:
- Fix TS2379 in use-translation.ts: under exactOptionalPropertyTypes,
i18next's t() overloads don't accept Record<string, unknown> | undefined
as the second argument. Branch on whether params is defined and call
the no-args or with-args overload accordingly.
- Bump @plane/i18n check:lint --max-warnings from 2 to 9. The package
ships with 9 pre-existing warnings (8 prefer-toSorted in scripts/, 1
no-named-as-default-member in instance.ts on a line untouched by my
changes). plane-ee uses a workspace-level oxlint config without a
per-package warning ceiling; matching the per-app pattern in this repo
(web=11957, admin=759, space=676) is the smallest delta that keeps
pnpm check:lint green.
Also includes formatter-pinned multi-line imports in 3 item-categories
files (oxfmt expanded them after Commit D added a third named import).
* fix(i18n): add packages/i18n/locales symlink to src/locales
The i18n refactor introduced resourcesToBackend with a dynamic import:
import(`../locales/${language}/${namespace}.json`)
That path is relative to the source file's location. From src/core/instance.ts
it correctly resolves to src/locales/. But after tsdown bundling, the same
import call lives in dist/index.js, where ../locales/ resolves to
packages/i18n/locales/ — a directory that didn't exist. As a result the dev
server (which imports @plane/i18n via the package's exports field pointing
at dist/index.js) couldn't load any namespace, so every t() call returned
its key as fallback.
Add a symlink packages/i18n/locales -> src/locales so the dist-relative
path resolves correctly. Same fix plane-ee uses (verified: identical blob
mode 120000, SHA a4829b5). Keeps tsdown.config.ts and package.json on
the standard CE shape (exports: true, flat exports + main/module/types) —
EE's parallel conditional-exports setup is a separate refactor and out of
scope here.
* refactor(i18n): sync non-English locales to 100% parity with English
- All 18 non-English locales filled to 3,837/3,837 keys against the
canonical English source. Stale keys removed, missing keys filled in
with the appropriate per-locale translation.
- New scripts/lib/locale-io.ts module shared between sync-check and
future tooling. readJsonFile() wraps JSON.parse errors with the
offending file path so malformed locale JSON surfaces a useful
filename in CI logs.
- New .github/workflows/i18n-sync-check.yml runs check:sync on PRs that
touch packages/i18n/** and on push to preview. Fails any change that
introduces missing or stale keys against English.
- Pin tsx@4.20.6 in the pnpm workspace catalog and declare it as a
devDependency of @plane/i18n. Replace npx tsx@4.19.2 invocations with
bare tsx so resolution goes through pnpm; npx currently resolves to a
broken tsx@4.21.0 that pulls an unpublished esbuild range.
---------
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
…ectMember (#8966) * test(api): add regression tests for create-project endpoint Cover three scenarios: - project_lead set to the creator's own user_id - project_lead set to a different workspace member - project_lead omitted (baseline) The first two currently fail on preview because of a UUID coercion bug in ProjectMember.objects.create — see follow-up commit. * fix(api): pass project_lead_id (not User instance) when creating ProjectMember The create-project endpoint built a ProjectMember row with member_id=serializer.instance.project_lead, which resolves to a User instance via Django's related descriptor instead of a UUID. Django's UUIDField coercion then fails with AttributeError: 'User' object has no attribute 'replace', which the generic exception handler converts to a 400 "Please provide valid detail" — but only after the Project row was already persisted, leaving an orphaned project without default states. Fix: - Use project_lead_id (FK ID, no descriptor lookup) on both the guard comparison and the ProjectMember creation. - Wrap the post-save flow in transaction.atomic() so any future exception triggers a clean rollback. - Defer model_activity.delay() with transaction.on_commit() so the activity log only fires after a successful commit. - Capture the exception with log_exception() in the generic catch so future regressions surface in api logs. Note: a related data integrity issue exists where ProjectCreateSerializer doesn't create a ProjectIdentifier row (unlike its frontend counterpart). Out of scope here, will follow up in a separate PR. * fix(api): return 500 on unexpected errors and harden project create Address review feedback from @sriramveeraghanta on PR #8966: - The catch-all `except Exception` now returns 500 instead of 400. Reusing the generic 400 response on a server-side crash was the anti-pattern that hid the original ghost-create bug for nine months; a 500 lets clients distinguish between "bad input" and "server fault". - The `IntegrityError` branch no longer falls through silently when the message is unrecognised. It re-raises so the catch-all `except` logs the exception and returns a 500. - `transaction.on_commit()` now schedules `model_activity.delay` via `functools.partial` instead of a lambda, avoiding late-binding closure semantics. - `ProjectCreateSerializer.validate()` now rejects `project_lead` values that are not active workspace members, surfacing the error under the `project_lead` field key (rather than as `non_field_errors`) so API clients can react programmatically. * test(api): harden assertions and cover rollback / workspace-membership Address review feedback from @sriramveeraghanta on PR #8966: - The three existing tests now look up the created project via `Project.objects.get(id=response.data["id"])` instead of `.first()`. The assertion now fails for the right reason if the wrong project is returned by the endpoint. - New `test_create_project_with_lead_not_in_workspace_returns_400` guards the workspace-membership validation added to `ProjectCreateSerializer.validate()`. Expects a 400 with a field-shaped error and zero rows persisted. - New `test_model_activity_not_called_on_rollback` locks in the `transaction.on_commit()` semantics: when an exception is raised inside the atomic block (forced via mocking `State.objects.bulk_create`), the response is 500, no Project / ProjectMember / State rows are persisted, and the deferred `model_activity.delay` task is never dispatched. This prevents a future refactor from silently regressing the rollback contract. * fix(api): mark on_commit dispatch as robust against broker failures Address coderabbit re-review feedback on PR #8966. Without robust=True, an exception raised by model_activity.delay (e.g., a Celery broker outage) propagates out of the on_commit callback and is caught by the outer `except Exception` handler, which returns a 500 despite the project, ProjectMember rows and default States having already been committed. The client sees a 500 and assumes the create failed — the same class of mismatch between actual state and reported status that the original bug exhibited, just at the post-commit phase. Set robust=True so Django logs the dispatch failure internally via the standard transaction logger and the response stays 201, reflecting the persisted state. Switch from `functools.partial` to a nested function (`_dispatch_model_activity`) for the on_commit callable. Django's robust on_commit logging path reads `func.__qualname__` to format the error message; `partial` objects lack that dunder by default, and the `functools.update_wrapper` workaround turns out to be brittle when the wrapped callable is replaced by a Mock (which the new regression test relies on). A nested function exposes `__qualname__` natively, and the locals it closes over are bound at definition time and never rebound before the callback fires, so the late-binding-closure motivation for `partial` over `lambda` does not apply here. A new test, test_response_still_201_when_broker_dispatch_fails, mirrors test_model_activity_not_called_on_rollback to lock in the post-commit branch. It uses `@pytest.mark.django_db(transaction=True)` so the surrounding test transaction is actually committed and the `on_commit` callback fires (the default wrapper suppresses it via rollback). * fix(api): handle unrecognised IntegrityError consistently Address coderabbit re-review feedback on PR #8966. The previous fix used `raise` inside the IntegrityError handler with the intent of "letting the catch-all `except Exception` below log it and return 500". Coderabbit correctly flagged that `raise` exits the try/except entirely — sibling except clauses don't fire — so unrecognised integrity errors actually skipped `log_exception` and the consistent 500 JSON shape, contradicting the stated intent. Replicate the catch-all behaviour inline: log the exception via `log_exception(e)` and return the same generic 500 response with `{"error": "An unexpected error occurred"}`. The client now gets a uniform error shape regardless of which `except` branch handled it. --------- Co-authored-by: Jose Antonio Martinez <257598434+jamartineztelecoengineer84-dotcom@users.noreply.github.com>
#9024) * fix: comment quick-actions menu hidden when no actions are available * refactor: remove dead code
The community AIO Dockerfile declared the VOLUME instruction with
single quotes: VOLUME ['/app/data', '/app/logs']. Docker's JSON (exec)
form requires double quotes; with single quotes the line is parsed as
the shell form and the bracket/comma tokens become literal volume
paths ('[/app/data,' and '/app/logs]').
Docker tolerated these non-absolute anonymous volume paths at container
create time until Engine 29.5.0, which now rejects them with
"invalid mount config for type volume: invalid mount path: '[/app/data,'
mount path must be absolute", breaking `docker compose up --force-recreate`
and any container recreation for the AIO community image.
Switching to the valid JSON array form fixes the parsing.
* fix(web): fallback when requestIdleCallback is unavailable * refactor: improve idle task scheduling safety in render-if-visible
The webhook dispatcher validated webhook.url before posting but called requests.post() without allow_redirects=False, so a webhook destination could return a 3xx redirect to an internal address (cloud metadata, internal services) and have the worker fetch it and persist the response body to webhook_logs, readable back via the webhook-logs API. Pass allow_redirects=False so the original validate_url() guard is authoritative. Matches the pattern already used by safe_get() in work_item_link_task.py and the behavior of GitHub/Stripe/Slack webhooks.
* chore(api): add docker compose test runner
Adds docker-compose-test.yml at the repo root that boots an isolated
postgres / valkey / rabbitmq / minio stack with health checks and tmpfs
data dirs, then runs pytest against it and exits. Includes a usage doc
under apps/api/tests/RUNNING_TESTS.md and a pointer in AGENTS.md.
Prereq: ./setup.sh (generates apps/api/.env).
Usage:
docker compose -f docker-compose-test.yml up --build \
--abort-on-container-exit --exit-code-from api-tests
docker compose -f docker-compose-test.yml down -v
* fix(api): correct bugs surfaced by the pytest suite
Five small bugs caught by enabling the pytest contract suite end-to-end.
Each is independently justifiable:
- api/serializers/cycle.py + api/views/cycle.py: CycleCreateSerializer.validate
required project_id in the request body, but the view only ever passes
it through the URL kwarg. Cycle create/update via the public API was
returning 400 "Project ID is required". Read project_id from
serializer context (passed by the view) in addition to body/instance.
- app/views/api.py: ApiTokenEndpoint.get(pk) and patch(pk) did not filter
out is_service=True tokens, so a user could read and modify service
tokens through the user token endpoint. The list mode and delete
already filter is_service=False; aligned the other two.
- bgtasks/work_item_link_task.py: validate_url_ip checked hostname before
scheme, so file:///etc/passwd raised "No hostname found" instead of
the documented "Only HTTP and HTTPS" error. Swapped the order so the
scheme guard matches the docstring intent.
- utils/path_validator.py: get_allowed_hosts used `WEB_URL or APP_BASE_URL`
so when both are configured to different hosts (the standard local
setup: WEB_URL=:8000, APP_BASE_URL=:3000), only one was added to the
allow-list. Redirects to APP_BASE_URL then had their next_path stripped
because the host wasn't allowed. Include every configured base URL.
* chore(api): align pytest tests with current behavior, clear warnings
Test-side fixes paired with the product fixes in the previous commit, plus
deprecation cleanup that drops the test run from 104 warnings to 0.
Tests:
- tests/contract/api/test_cycles.py: project fixture sets cycle_view=True;
the Project model defaults the flag to False, so cycle create/update
always tripped "Cycles are not enabled for this project".
- tests/contract/app/test_authentication.py: next_path uses "/workspaces"
(validate_next_path rejects values without a leading slash and returns
empty, which dropped the path from the redirect URL).
- tests/unit/bg_tasks/test_copy_s3_objects.py: mocked sync_with_external_service
now returns description_json; the task unconditionally writes the value
back to the Issue, and Issue.description_json is NOT NULL on UPDATE.
- tests/unit/utils/test_url.py: three length-limit tests placed the URL at
char 970+ on a single line, which contains_url truncates away as ReDoS
defense (500-char per-line cap). Restructured to keep test intent intact
while staying inside the per-line window.
Warning cleanup (104 → 0):
- settings/common.py: removed USE_L10N=True (deprecated in Django 4.0,
removed in 5.0; default is True).
- celery.py, settings/local.py, settings/production.py: pythonjsonlogger
moved jsonlogger → json; update the import / formatter path.
- Replace flat pr-description.md / release-notes.md with per-skill folders - Add new branch-name and translate skills - Update release-notes skill to match the GitHub Releases format (v1.2.0)
* fix: harden API token handling against rate-limit tampering and plaintext logging - Make `allowed_rate_limit` read-only on APITokenSerializer so users can no longer raise their own API token rate limit via PATCH (GHSA-xfgr-2x3f-g2cf). - Stop persisting API keys in plaintext in APITokenLogMiddleware: store a SHA-256 hash as the token identifier and redact sensitive request headers (X-Api-Key, Authorization, Cookie) before logging (GHSA-r5p8-cj3q-38cc). * refactor: remove MongoDB log sink and add per-log-type retention Logs are now written to and cleared from PostgreSQL only; MongoDB is no longer used as a log sink or archive. - Drop the MongoDB write/archival paths from the API request logger, the webhook log writer, and the cleanup tasks; Postgres is the sole sink. - Cleanup tasks now hard-delete expired rows in batches via `all_objects` (rows are removed immediately, not soft-deleted). - Add env-backed, per-log-type retention settings: API activity logs (API_ACTIVITY_LOG_RETENTION_DAYS, default 14), webhook logs (WEBHOOK_LOG_RETENTION_DAYS, default 14), email logs (EMAIL_LOG_RETENTION_DAYS, default 7). HARD_DELETE_AFTER_DAYS no longer drives any log cleanup. - Delete settings/mongo.py, remove MONGO_DB_* settings and the plane.mongo loggers, and drop the pymongo dependency. * chore: gitignore local advisories.md notes file * fix: use keyed HMAC-SHA256 for API token log identifier Address CodeQL "weak hashing of sensitive data" by hashing the API key with a SECRET_KEY-keyed HMAC instead of a bare SHA-256. The identifier is a non-reversible tokenization of a high-entropy key (not password storage); keying it also prevents precomputing the digest from a known key value. * chore: address review feedback on log cleanup and request logging - process_logs accepts extra kwargs so jobs enqueued by an older release (with a mongo_log arg) don't fail during a rolling deploy. - Log-cleanup batch delete failures are logged and skipped rather than aborting the run, so a single bad batch can't block the rest. - Extend logger middleware test to assert Authorization and Cookie headers are redacted; add a test that a failing cleanup batch is swallowed. * fix: fall back to default when a log retention env value is invalid Negative (or unparseable) retention values would compute a future cutoff and delete every log row. The retention settings now fall back to their defaults in that case via a shared `_retention_days` helper.
…9147) * chore: bump turbo to 2.9.14, migrate pnpm config to workspace yaml - Bump turbo from 2.9.4 to 2.9.14 in root package.json and the four production Dockerfiles (web, live, admin, space). - Move pnpm.overrides, onlyBuiltDependencies, and ignoredBuiltDependencies from package.json into pnpm-workspace.yaml. pnpm v10+ no longer reads the pnpm field in package.json, so the full overrides block and most of onlyBuiltDependencies were being silently ignored. - Add @plane/utils as a workspace dependency to the live server. * chore: drop unused allowBuilds block, bump lodash-es to 4.18.1 - Remove the `allowBuilds` block from pnpm-workspace.yaml. It is not a recognized pnpm v10/v11 key and its values were inconsistent with the actual `onlyBuiltDependencies` / `ignoredBuiltDependencies` configuration. - Bump `lodash-es` catalog entry from 4.18.0 to 4.18.1. With overrides now applied workspace-wide, 4.18.0 (marked deprecated as a "bad release") was being enforced everywhere. * fix: use pnpm v11 allowBuilds in place of removed legacy keys `onlyBuiltDependencies` and `ignoredBuiltDependencies` were removed in pnpm v11. They were being silently ignored on this branch, which caused `ERR_PNPM_IGNORED_BUILDS` to fail CI under `--frozen-lockfile`. Replace them with the v11-native `allowBuilds:` block, mapping the previous allowlist to `true` and the previous denylist (sharp) to `false`. Locally verified that the build scripts for @parcel/watcher, @swc/core, esbuild, and msgpackr-extract now run on install.
#9156) * [WEB-7447] feat: migrate CE telemetry from OTLP traces to OTLP metrics Replace span-based tracing (tracer.py) with OTLP observable gauges, mirroring the approach already used in plane-ee. Key changes: - Add otlp_endpoints.py — shared gRPC/HTTP endpoint helpers - Add telemetry_metrics.py — push_instance_metrics task using MeterProvider + observable gauges (service name: plane-ce-api) - User count excludes bots (is_bot=False) - Page count excludes bot-owned private pages only - Domain derived from WEB_URL env var - Celery beat entry replaced with timedelta schedule + configurable METRICS_PUSH_INTERVAL_MINUTES (default 360 min) - Add explicit opentelemetry-exporter-otlp-proto-grpc dep - Delete tracer.py and telemetry.py (no longer needed) Co-authored-by: Plane AI <noreply@plane.so> * fix: address review comments on CE telemetry metrics - harden grpc_endpoint_from_url for scheme-less OTLP_ENDPOINT values (e.g. "telemetry.plane.so:4317") by prepending "//" before urlparse - fix WEB_URL domain extraction for scheme-less values with same approach - replace N+1 workspace count queries (6×N) with 6 batched annotate(Count) aggregation queries — reduces DB load significantly at WORKSPACE_METRICS_LIMIT - add deterministic ordering (order_by created_at) to workspace slice - harden METRICS_PUSH_INTERVAL_MINUTES env parsing with try/except guard and positive-value validation to avoid crash on malformed input Co-authored-by: Plane AI <noreply@plane.so> * fix: cap METRICS_PUSH_INTERVAL_MINUTES to prevent timedelta overflow Add upper-bound check (10_000_000 minutes) and catch OverflowError alongside ValueError so an arbitrarily large env value cannot crash worker startup via timedelta(minutes=...) OverflowError. Co-authored-by: Plane AI <noreply@plane.so> --------- Co-authored-by: Plane AI <noreply@plane.so>
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.